home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / GL / curve / curve.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  11KB  |  530 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  * curve.c
  19.  *
  20.  * This is the main file for the Curve Demo. 
  21.  * 
  22.  * This program gives a demonstration of the use of the GL 
  23.  * graphics library to create different types of curves in both 
  24.  * two and three dimensions. The user may select among different
  25.  * types of splines to approximate the curve, view the the control
  26.  * points that define the curve, manipulate the control points to see
  27.  * the effect on the resulting curve, as well as a host of other
  28.  * "whiz-bangs" including setting the curve in motion, viewing the
  29.  * curve in 3D perspective, and more.
  30.  *
  31.  * OPERATION
  32.  * Type
  33.  * curve <ENTER>
  34.  * to begin the demo. To quit, select quit from the menu, or press the
  35.  * ESC key.
  36.  *
  37.  * LEFT MOUSE
  38.  * adds a control point in both 2D and 3D modes. Control points are
  39.  * given a random z value, which is apparent in 3D mode. If the left
  40.  * mouse button is held while adding a point, that point may be moved
  41.  * around. Otherwise, control points may be moved after they are added
  42.  * using the...
  43.  *
  44.  * MIDDLE MOUSE
  45.  * In 2D mode, the middle allows a control point to be moved by
  46.  * pointing at it, pressing and holding the middle button, then
  47.  * dragging the control point to a new location.
  48.  * In 3D mode, the middle mouse allows manipulation of the view
  49.  * volume. When the middle mouse is pressed and dragged within the
  50.  * volume, the volume is rotated trackball style around the world x
  51.  * and y axes. When the middle mouse is pressed and dragged outside
  52.  * the view volume, the volume is rotated about the z axis.
  53.  *
  54.  * RIGHT MOUSE
  55.  * brings up the menus. Menus are fairly self explanatory. The Options
  56.  * menu allows the user to add all kinds of whizzy things to the
  57.  * display. For some real fun, put the program in 3D mode, then turn
  58.  * markers off, smear on, then motion on. Toss in a handful of control
  59.  * points (with the left mouse button), then sit back and enjoy.
  60.  * The truly daring may manipulate the view volume (with the middle
  61.  * mouse) while all this is hapening.
  62.  *
  63.  * BACKSPACE Key
  64.  * deletes the control point nearest to the cursor in both 2D and 3D
  65.  * modes.
  66.  * 
  67.  * Written by Howard Look for Silicon Graphics, Inc.
  68.  * Based upon the initial program written by Rocky Rhodes and Herb Kuta
  69.  * Plenty of help from Thant Tessman^, Gavin Bell and Keith Seto
  70.  *
  71.  * ^Twinkies for convex hulls and tons of help
  72.  * 
  73.  * June, 1989
  74.  * 
  75.  */
  76.  
  77.  
  78. #include <stdio.h>
  79. #include <gl.h>
  80. #include <device.h>
  81. #include <math.h>
  82. #include <fmclient.h>
  83. #include "event.h"
  84. #include "curve.h"
  85. #include "spaced.h"
  86.  
  87.  
  88.  
  89. /* Prototypes */
  90. void init_window(char *argv[]);
  91. void init_events(void);
  92. void redraw(void);
  93. void process_left_down(void);
  94. void process_left_up(void);
  95. void process_middle_down(void);
  96. void process_middle_up(void);
  97. void process_mouse_motion(void);
  98. void draw_instructions(Boolean);
  99. void quit(void);
  100. void init_fonts(void);
  101. void help(void);
  102. void end_help(void);
  103. Boolean helping(void);
  104.  
  105. extern void init_menus(void);
  106. extern void init_basis(void);
  107. extern void init_linestyles(void);
  108. extern void add_control_point(void);
  109. extern void delete_control_point(int);
  110. extern void move_control_point(int);
  111. extern void draw_display(void);
  112. extern void clear_window(void);
  113. extern Boolean hit_control_point(int *);
  114.  
  115. /* Environment variables */
  116. int        curve_basis, 
  117.         display_mode, 
  118.         curve_precision,
  119.         speed, 
  120.         line_style, 
  121.         whizbang;
  122. Boolean    markers,
  123.         hulls,
  124.         motion, 
  125.         smear,
  126.         rotating;
  127.  
  128. extern Boolean moving;
  129.  
  130. /* type of hardware we are running on */
  131. int hardware;
  132.     
  133.  
  134. /* Is drawing active ? */
  135. Boolean    draw_active;
  136.  
  137.  
  138. /* Lower left corner of the window */
  139. int origin_x, origin_y;
  140.  
  141.  
  142. /* Size of the window */
  143. int size_x, size_y;
  144.  
  145. /* Window's aspect ratio, x/y */
  146. float aspect;
  147.  
  148. extern Coord geometry[MAX_MARKERS][3];
  149. extern int nailed_marker;
  150. extern Matrix everything_matrix;
  151.  
  152. void main(int argc, char *argv[])
  153. {
  154.  
  155.     /* Don't hog the graphics unless necessary */
  156.     draw_active = FALSE;
  157.  
  158.     /* initialize everything */
  159.     init_window(argv);
  160.  
  161.     init_fonts();
  162.     draw_instructions(TRUE);
  163.     
  164.     init_basis();
  165.     init_linestyles();
  166.     init_menus();
  167.     init_events();
  168.     
  169.     help();
  170.  
  171.     /* event() looks for the events (as in init_events) and passes 
  172.        them on to the appropriate routines */
  173.     while(TRUE)
  174.         event();
  175. }
  176.  
  177.  
  178. /* 
  179.  * Opens the window and sets up the graphic mode.
  180.  */
  181. void init_window(char *argv[])
  182. {
  183.     char *t, *strrchr();
  184.  
  185.     if (getgdesc(GD_BITS_NORM_ZBUFFER) == 0)
  186.     {
  187.         system("inform 'Your system must have a z-buffer to run curve'");
  188.         exit(1);
  189.     }
  190.  
  191.     keepaspect(1,1);
  192.     /* open the window with its invocation as the title (less the path) */
  193.     winopen((t=strrchr(argv[0], '/')) != NULL ? t+1 : argv[0]);
  194.  
  195.     /* 
  196.      * Assume that if we have fewer than 4 RGB bitplanes, may as
  197.      * well run in colorindex mode.
  198.      */
  199.     if (getgdesc(GD_BITS_NORM_DBL_RED) < 4)
  200.         hardware = ECLIPSE8;
  201.     else if (getgdesc(GD_BITS_NORM_DBL_RED) >= 8)
  202.         hardware = ECLIPSE24;
  203.     else
  204.         hardware = GT;
  205.  
  206.     doublebuffer();
  207.  
  208.     if (hardware != ECLIPSE8)
  209.         RGBmode();
  210.         
  211.     zbuffer(TRUE);
  212.     gconfig();
  213.     
  214.     glcompat(GLC_ZRANGEMAP, 0);
  215.  
  216.     getorigin(&origin_x, &origin_y);
  217.     getsize(&size_x, &size_y);
  218.  
  219.     aspect = (float)size_x/(float)size_y;
  220. }
  221.  
  222.  
  223. /* 
  224.  * Tells event manager what to pay attention to.
  225.  */
  226. void init_events(void)
  227. {
  228.     /* ESC key and WINQUIT quit the program */
  229.     add_event(ANY, ESCKEY, UP, quit, 0);
  230.     qdevice(ESCKEY);
  231.     add_event(ANY, WINQUIT, ANY, quit, 0);
  232.     qdevice(WINQUIT);
  233.  
  234.     /* window redraw events */
  235.     add_event(ANY, REDRAW, ANY, redraw, 0);
  236.     qdevice(REDRAW);
  237.  
  238.     add_event(ANY,  LEFTMOUSE, DOWN, process_left_down, NULL);
  239.     add_event(ANY,  LEFTMOUSE, UP, process_left_up, NULL);
  240.     qdevice(LEFTMOUSE);
  241.  
  242.     add_event(ANY,  MIDDLEMOUSE, DOWN, process_middle_down, NULL);
  243.     add_event(ANY,  MIDDLEMOUSE, UP, process_middle_up, NULL);
  244.     qdevice(MIDDLEMOUSE);
  245.  
  246.     add_event(ANY, MOUSEX, ANY, process_mouse_motion, NULL);
  247.     add_event(ANY, MOUSEY, ANY, process_mouse_motion, NULL);
  248.     
  249.     /* Backspace deletes the nearest control marker */
  250.     add_event(ANY, BACKSPACEKEY, DOWN, delete_control_point, NULL);
  251.     qdevice(BACKSPACEKEY);
  252.  
  253.     /* Draw the curve whenever the user does not request anything */
  254.     /* i.e., there are no events happening */
  255.     add_update(&draw_active, draw_display, NULL);
  256. }
  257.  
  258.  
  259. /*
  260.  * Called by the event manager whenever a redraw event occurs,
  261.  * e.g. when the window is resized.
  262.  */
  263. void redraw(void)
  264. {
  265.         getorigin(&origin_x, &origin_y);
  266.         getsize(&size_x, &size_y);
  267.         aspect = (float)size_x/(float)size_y;
  268.         viewport(0, size_x-1, 0, size_y-1);
  269.  
  270.         if (helping())
  271.             help();
  272.         else
  273.             draw_display();
  274. }
  275.  
  276.  
  277. void process_left_down(void)
  278. {
  279.     int marker;
  280.     
  281.     end_help();
  282.     
  283.     if (hit_control_point(&marker))
  284.         move_control_point(marker);
  285.     else
  286.         add_control_point();
  287. }
  288.  
  289.  
  290. void process_left_up(void)
  291. {
  292.     unqdevice(MOUSEX);
  293.     unqdevice(MOUSEY);
  294.  
  295.     moving = FALSE;
  296.     end_spaced();
  297.     draw_display();
  298. }    
  299.  
  300.  
  301. void process_middle_down(void)
  302. {
  303.     int marker;
  304.  
  305.     end_help();
  306.     
  307.     if (display_mode == TWO_D)
  308.     {
  309.         if (hit_control_point(&marker))
  310.             move_control_point(marker);
  311.     }
  312.     else
  313.         rotate_view_volume();
  314. }
  315.  
  316.  
  317. void process_middle_up(void)
  318. {
  319.     unqdevice(MOUSEX);
  320.     unqdevice(MOUSEY);
  321.  
  322.     rotating = FALSE;
  323.     moving = FALSE;
  324. }
  325.  
  326.  
  327.  
  328. /* limits of the view volume */
  329. Coord box_limit[3][2] =
  330.     {    { -1.0, 1.0},
  331.         { -1.0, 1.0},
  332.         { -1.0, 1.0}
  333.     };
  334.  
  335.     
  336. void process_mouse_motion(void)
  337. {
  338.     
  339.     if (rotating && getbutton(MIDDLEMOUSE))
  340.     {
  341.         update_rotation();
  342.         draw_display();
  343.     }
  344.     else if (moving && (getbutton(LEFTMOUSE)||getbutton(MIDDLEMOUSE)))
  345.     {
  346.         if (display_mode == TWO_D)
  347.             track_motion();
  348.         else
  349.             spaced(everything_matrix, geometry[nailed_marker], box_limit);
  350.             
  351.         draw_display();
  352.     }
  353.  
  354. }
  355.  
  356.  
  357.  
  358.  
  359. /*
  360.  * Outta here.
  361.  */
  362. void quit(void)
  363. {
  364.     gexit();
  365.     exit(0);
  366. }
  367.  
  368.  
  369.  
  370.  
  371. /*
  372.  * Routines for writing the intro messages to the screen.
  373.  */
  374.  
  375. double min(double x, double y)
  376. {
  377.     if (x < y)
  378.         return x;
  379.     else
  380.         return y;
  381. }
  382.  
  383. static fmfonthandle base_font, scaled_font;
  384.  
  385.  
  386.  
  387. void init_fonts(void)
  388. {
  389.     fminit();
  390.     base_font = fmfindfont("Times-Roman");
  391. }    
  392.  
  393.  
  394. void setup_string(char str[100], int size, Coord *half)
  395. {
  396.     double h_size, v_size, f_size;
  397.     Coord length;
  398.     
  399.     h_size = (double)size_x/(double)size;
  400.     v_size = (double)size_y/(double)size;
  401.     f_size = min(h_size, v_size);
  402.     scaled_font = fmscalefont(base_font, f_size);
  403.     fmsetfont(scaled_font);
  404.  
  405.     length = fmgetstrwidth(scaled_font, str);
  406.     *half = (Coord)(length/size_x);
  407. }
  408.  
  409. static int looking_at_help;
  410. static int active_state;
  411.  
  412. void help(void)
  413. {
  414.     if (!looking_at_help)
  415.     {
  416.         looking_at_help = TRUE;
  417.  
  418.         active_state = draw_active;
  419.         draw_active = FALSE;
  420.     }
  421.     draw_instructions(FALSE);
  422. }
  423.  
  424. void end_help(void)
  425. {
  426.     if (looking_at_help)
  427.     {
  428.         looking_at_help = FALSE;
  429.         draw_active = active_state;
  430.     }
  431. }
  432.  
  433. Boolean helping(void)
  434. {
  435.     return looking_at_help;
  436. }
  437.  
  438. void draw_instructions(Boolean initializing)
  439. {
  440.     Coord half;
  441.     char str[100];
  442.  
  443.     ortho2(-1.0, 1.0, -1.0, 1.0);
  444.     czclear(0,getgdesc(GD_ZMAX));
  445.     depthcue(FALSE);
  446.     
  447.     sprintf(str,"Curve");
  448.     setup_string(str,20,&half);    
  449.     cmov2(0.0 - half, 0.7);
  450.     if (hardware == ECLIPSE8)
  451.         color(GREEN);
  452.     else
  453.         cpack(0xFF00);
  454.     fmprstr(str);
  455.  
  456.     sprintf(str,"Interactive Cubic Curve Demonstration");
  457.     setup_string(str,40,&half);    
  458.     cmov2(0.0 - half, 0.6);
  459.     if (hardware == ECLIPSE8)
  460.         color(GREEN);
  461.     else
  462.         cpack(0xFF00);
  463.     fmprstr(str);
  464.  
  465.     sprintf(str,"Press the left mouse button to add a new control point,");
  466.     setup_string(str,50,&half);    
  467.     cmov2(0.0 - half, 0.3);
  468.     if (hardware == ECLIPSE8)
  469.         color(WHITE);
  470.     else
  471.         cpack(0xFFFFFF);
  472.     fmprstr(str);
  473.  
  474.     sprintf(str,"or to move an existing control point.");
  475.     setup_string(str,50,&half);    
  476.     cmov2(0.0 - half, .24);
  477.     fmprstr(str);
  478.  
  479.     sprintf(str,"In 3D mode, use the middle mouse button");
  480.     setup_string(str,50,&half);    
  481.     cmov2(0.0 - half, .14);
  482.     fmprstr(str);
  483.  
  484.     sprintf(str,"to rotate the view volume.");
  485.     setup_string(str,50,&half);    
  486.     cmov2(0.0 - half, .08);
  487.     fmprstr(str);
  488.  
  489.     sprintf(str,"Press the right mouse button to bring up a pop-up menu.");
  490.     setup_string(str,50,&half);    
  491.     cmov2(0.0 - half, -.02);
  492.     fmprstr(str);
  493.  
  494.     sprintf(str,"Choose \"Display Mode\" to switch from 2D to 3D.");
  495.     setup_string(str,50,&half);    
  496.     cmov2(0.0 - half, -.08);
  497.     fmprstr(str);
  498.  
  499.     sprintf(str,"For some interesting shapes, choose a \"Whizbang\" from the");
  500.     setup_string(str,50,&half);    
  501.     cmov2(0.0 - half, -.18);
  502.     fmprstr(str);
  503.  
  504.     sprintf(str,"Options menu.");
  505.     setup_string(str,50,&half);    
  506.     cmov2(0.0 - half, -.24);
  507.     fmprstr(str);
  508.  
  509.     sprintf(str,"For more information, please see the man page.");
  510.     setup_string(str,50,&half);    
  511.     cmov2(0.0 - half, -.34);
  512.     fmprstr(str);
  513.  
  514.     if (initializing)
  515.     {
  516.         sprintf(str,"Initializing. Please Wait...");
  517.         setup_string(str,40,&half);    
  518.         cmov2(0.0 - half, -.70);
  519.         if (hardware == ECLIPSE8)
  520.             color(RED);
  521.         else
  522.             cpack(0xFF);
  523.         fmprstr(str);
  524.     }
  525.  
  526.             
  527.     swapbuffers();
  528. }
  529.  
  530.